﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.ComponentModel;
using FieldLib;
using FieldLib.Comm;
using FieldDevice.ModBus;

namespace FieldDevice.Devices
{
    class DeviceREF542Plus : Device
    {
        public DeviceREF542Plus(byte address)
            : base(DeviceCategory.HighVoltageDevice, address)
        {
            Initialize();
        }

        public enum FloatRegisters
        {
            Ia,//0
            Ib,//1
            Ic,//2
            Uab,//3
            Ubc,//4
            Uca,//5
            Ua,//6
            Ub,//7
            Uc,//8
            PF,//9
            P,//10
            Q,//11
            S,
            Kwh,//12
            Kvarh//13
        }


        public const ushort Register_Ia_Hi = 0x0000;        //A相电流高位
        public const ushort Register_Ia_Low = 0x0001;       //A相电流低位
        public const ushort Register_Ib_Hi = 0x0002;        //B相电流高位    
        public const ushort Register_Ib_Low = 0x0003;       //B相电流低位
        public const ushort Register_Ic_Hi = 0x0004;        //C相电流高位
        public const ushort Register_Ic_Low = 0x0005;       //C相电流低位
        public const ushort Register_Uab_Hi = 0x006;        //AB线电压高位
        public const ushort Register_Uab_Low = 0x007;       //AB线电压低位
        public const ushort Register_Ubc_Hi = 0x008;        //BC线电压高位    
        public const ushort Register_Ubc_Low = 0x009;       //BC线电压低位
        public const ushort Register_Uca_Hi = 0x00a;        //CA线电压高位
        public const ushort Register_Uca_Low = 0x00b;       //CA线电压低位
        public const ushort Register_Ua_Hi = 0x000c;        //A相电压高位
        public const ushort Register_Ua_Low = 0x000d;       //A相电压低位
        public const ushort Register_Ub_Hi = 0x000e;        //B相电压高位
        public const ushort Register_Ub_Low = 0x000f;       //B相电压低位
        public const ushort Register_Uc_Hi = 0x0010;        //C相电压高位
        public const ushort Register_Uc_Low = 0x0011;       //C相电压低位
        public const ushort Register_PF_Hi = 0x0018;        //功率因数高位
        public const ushort Register_PF_Low = 0x0019;       //功率因数低位
        public const ushort Register_P_Hi = 0x001a;         //有功功率高位
        public const ushort Register_P_Low = 0x001b;        //有功功率低位
        public const ushort Register_Q_Hi = 0x001c;         //无功功率高位
        public const ushort Register_Q_Low = 0x001d;        //无功功率低位
        public const ushort Register_Kwh_Hi = 0x0020;       //有功电度高位
        public const ushort Register_Kwh_Low = 0x0021;      //有功电度低位
        public const ushort Register_Kvarh_Hi = 0x0022;     //无功电度高位
        public const ushort Register_Kvarh_Low = 0x0023;        //无功电度低位

        public const ushort Register_YX = 0x0000;       //遥信的寄存器地址   
        //private int value_IA = 0;
        //private int value_IB = 0;
        //private int value_IC = 0;
        //private int value_VA = 0;
        //private int value_VB = 0;
        //private int value_VC = 0;
        //private int value_Vab = 0;
        //private int value_Vbc = 0;
        //private int value_Vca = 0;
        //private int value_PF = 0;
        //private int value_P = 0;
        //private int value_Q = 0;
        //private int value_Kwh = 0;
        //private int value_Kvarh = 0;

        void Initialize()
        {
            RequestRegister(Register_Ia_Hi, 36); //0x24个计算器
            RequstRegister(Register_YX, 8, ModBus.ModBusFunction.READINPUTSTATUS);

            base.Thresholds.Add("Vab", new FloatValueThreshold("AB线电压", true, 10600f, "电压过高", true, 9800f, "电压过低", "V"));
            base.Thresholds.Add("Vbc", new FloatValueThreshold("BC线电压", true, 10600f, "电压过高", true, 9800f, "电压过低", "V"));
            base.Thresholds.Add("Vca", new FloatValueThreshold("CA线电压", true, 10600f, "电压过高", true, 9800f, "电压过低", "V"));
        }

        DateTime PreviousRecordTime;
        protected override void RequestRegister(ushort registeraddress, ushort datanumber)
        {
            ModBusPacket modframe = new ModBusPacket();
            modframe.Function = ModBusFunction.READINPUTREGISTER;
            modframe.SlaveAddress = (byte)this.ModbusAddress;
            modframe.DataAddressHi = (byte)(registeraddress >> 8);
            modframe.DataAddressLow = (byte)(registeraddress & 0x00FF);
            modframe.DataNumberHi = 0;
            modframe.DataNumberLow = (byte)(datanumber & 0x00FF);
            this.requests.Add(modframe);
        }

        protected void RequstRegister(ushort registeraddress, ushort datanumber, byte type)
        {
            ModBusPacket modframe = new ModBusPacket();
            modframe.Function = type;
            modframe.SlaveAddress = (byte)this.ModbusAddress;
            modframe.DataAddressHi = (byte)(registeraddress >> 8);
            modframe.DataAddressLow = (byte)(registeraddress & 0x00FF);
            modframe.DataNumberHi = 0;
            modframe.DataNumberLow = (byte)(datanumber & 0x00FF);
            this.requests.Add(modframe);
        }


        protected override byte ModBusReadCommand
        {
            get
            {
                return FieldDevice.ModBus.ModBusFunction.READINPUTREGISTER;
            }
        }

        public override void DebugReads()
        {
            if (DeviceManager.GlobalDeviceManager.ModBusIO.IsEmulation)
            {
                ushort Register0000_Begin = 0x0000;
                base.ReadAndUpdateValue(Register0000_Begin, 36);
                YXValues(Register_YX, 8);
                base.FireReadChangeEvent(null, 0.0f);
            }
            else
                base.DebugReads();
        }

        public override void TranslateRegister(ModBusPacket request, byte[] response)
        {
            string wrongmessage;
            if (!CheckReceiveModbusPacket(response, request.DataNumber, out wrongmessage))
                return;
            switch (request.Function)
            {
                case 0x02:
                    TranslateSwitchsRegister(response[3]);
                    break;
                case 0x04:
                    if (response[2] < 0x48)
                        throw new Exception("Wrong!");
                    int valuesnumber = response[2] / 4;
                    for (int i = 0; i < valuesnumber; i++)
                    {
                        this.Translate(response, i * 4 + 3, (ushort)(i * 2));
                        /*
                        float current = ui / 1000.0f;
                        switch (i)
                        {
                            case 0: base.RecordRead("IA", current); break;
                            case 1: base.RecordRead("IB", current); break;
                            case 2: base.RecordRead("IC", current); break;
                            case 3: base.RecordRead("VA", current); break;
                            case 4: base.RecordRead("VB", current); break;
                            case 5: base.RecordRead("VC", current); break;
                            default:
                                break;
                        }
                         */
                    }
                    break;
                default:
                    break;
            }

            DateTime now = DateTime.Now;
            int passedminute = ((now.Minute + 60) - PreviousRecordTime.Minute) % 60;
            if (passedminute > 1)
            {
                base.PowerQueues.RecordPowerItem(now, CurrentReads["EPI"], CurrentReads["EQL"], CurrentReads["PF"], request.ToBytes(), response);
                this.PreviousRecordTime = now;
            }
        }



        public void YXValues(ushort registeraddress, ushort datanumber)
        {
            ModBusPacket modframe = new ModBusPacket();
            modframe.Function = ModBusFunction.READINPUTSTATUS;
            modframe.SlaveAddress = (byte)this.ModbusAddress;

            modframe.DataAddressHi = (byte)(registeraddress >> 8);
            modframe.DataAddressLow = (byte)(registeraddress & 0x00FF);
            modframe.DataNumberHi = 0;
            modframe.DataNumberLow = (byte)(datanumber & 0x00FF);
            byte[] resultbytes = base.ReadRegister(modframe);
            byte value = resultbytes[3];
            TranslateSwitchsRegister(value);
            //if ((value & 0x01) != 0)
            //    RecordRead("H1_YX1", 1);
            //else
            //    RecordRead("H1_YX1", 0);
            //if ((value & 0x02) != 0)
            //    RecordRead("H1_YX2", 1);
            //else
            //    RecordRead("H1_YX2", 0);
            //if ((value & 0x04) != 0)
            //    RecordRead("H1_YX3", 1);
            //else
            //    RecordRead("H1_YX3", 0);
            //if ((value & 0x08) != 0)
            //    RecordRead("H1_YX4", 1);
            //else
            //    RecordRead("H1_YX4", 0);
            //if ((value & 0x10) != 0)
            //    RecordRead("H1_YX5", 1);
            //else
            //    RecordRead("H1_YX5", 0);
            //if ((value & 0x20) != 0)
            //    RecordRead("H1_YX6", 1);
            //else
            //    RecordRead("H1_YX6", 0);
            //if ((value & 0x40) != 0)
            //    RecordRead("H1_YX7", 1);
            //else
            //    RecordRead("H1_YX7", 0);
            //if ((value & 0x80) != 0)
            //    RecordRead("H1_YX8", 1);
            //else
            //    RecordRead("H1_YX8", 0);
        }

        public void TranslateSwitchsRegister(byte YXvalue)
        {
            if ((YXvalue & 0x01) != 0)
                RecordRead("H1_YX1", 1);            //遥信1
            else
                RecordRead("H1_YX1", 0);
            if ((YXvalue & 0x02) != 0)
                RecordRead("Handcart_Position", 1);            //手车位置
            else
                RecordRead("Handcart_Position", 0);
            if ((YXvalue & 0x04) != 0)
                RecordRead("OperationCondition_Work", 1);            //合闸
            else
                RecordRead("OperationCondition_Work", 0);
            if ((YXvalue & 0x08) != 0)
                RecordRead("OperationCondition_Stop", 1);            //开闸
            else
                RecordRead("OperationCondition_Stop", 0);
            if ((YXvalue & 0x10) != 0)
                RecordRead("H1_YX5", 1);            //遥信5
            else
                RecordRead("H1_YX5", 0);
            if ((YXvalue & 0x20) != 0)
                RecordRead("Grouding_Switch", 1);            //地刀接地
            else
                RecordRead("Grouding_Switch", 0);
            //if ((YXvalue & 0x40) != 0)
            //    RecordRead("H1_YX7", 1);            //遥信7
            //else
            //    RecordRead("H1_YX7", 0);
            //if ((YXvalue & 0x80) != 0)
            //    RecordRead("H1_YX8", 1);            //遥信8
            //else
            //    RecordRead("H1_YX8", 0);
        }
        protected override float Translate(byte[] response, int begin, ushort registeraddress)
        {
            uint ui = FieldLib.Utility.BytesToUInt_SmallEndian(response, begin);
            try
            {
                switch (registeraddress)
                {
                    case Register_Ia_Hi:RecordRead("IA", ui / 1000.0f);break;
                    case Register_Ib_Hi:RecordRead("IB", ui / 1000.0f);break;
                    case Register_Ic_Hi:RecordRead("IC", ui / 1000.0f);break;
                    case Register_Ua_Hi:RecordRead("VA", ui / 10.0f);break;
                    case Register_Ub_Hi:RecordRead("VB", ui / 10.0f);break;
                    case Register_Uc_Hi:RecordRead("VC", ui / 10.0f);break;
                    case Register_Uab_Hi:RecordRead("Vab", ui / 1000.0f);break;
                    case Register_Ubc_Hi:RecordRead("Vbc", ui / 1000.0f);break;
                    case Register_Uca_Hi:RecordRead("Vca", ui / 1000.0f);break;
                    case Register_P_Hi:RecordRead("P", ui );break;
                    case Register_Q_Hi:RecordRead("Q", ui);break;
                    case Register_PF_Hi:RecordRead("PF", ui/1000.0f);break;
                    case Register_Kwh_Hi:RecordRead("EPI", ui);break;
                    case Register_Kvarh_Hi:RecordRead("EQL", ui);break;
                    default:
                        break;
                }

            }
            catch
            {
                throw new NotImplementedException();
            }
            return 0.0f;
        }

        public override void Draw(System.Drawing.Graphics g, System.Drawing.Pen pen, bool isSelected, System.Drawing.SizeF zoom, System.Drawing.Point offset)
        {
            SolidBrush brush = new System.Drawing.SolidBrush(pen.Color);
            base.Draw(g, pen, isSelected, zoom, offset);
            Point p = offset;
            g.DrawString("有功功率:" + ((this.CurrentReads["P"]) / 1000.0f).ToString("F2") + " kW", font, brush, p.X, p.Y + 66);
            g.DrawString("无功功率:" + ((this.CurrentReads["Q"]) / 1000.0f).ToString("F2") + " kW", font, brush, p.X, p.Y + 88);
            g.DrawString("功率因素:" + ((this.CurrentReads["PF"]) / 1000.0f).ToString("F2") + " COSφ", font, brush, p.X, p.Y + 110);
        }


        protected override DeviceConfigBase GetDeviceConfig()
        {
            return Config;
        }

        protected override void SetDeviceConfig(Device.DeviceConfigBase config)
        {
            if (config is REF542PlusConfig)
            {
                base.SetDeviceConfig(config);
                this.Config = (REF542PlusConfig)config;
            }
        }

        REF542PlusConfig Config = new REF542PlusConfig();
        public class REF542PlusConfig : DeviceConfigBase
        {
            public REF542PlusConfig()
            {
                this.VoltageUpperThreshold = 10600f;
                this.VoltageLowerThreshold = 9800f;
            }

            [Category("电表参数"), Description("电压超高报警门限")]
            public float VoltageUpperThreshold { get; set; }
            [Category("电表参数"), Description("电压超低报警门限")]
            public float VoltageLowerThreshold { get; set; }
        }
    }
}
